package com.shao.loadBalance.impl;

import com.shao.SrpcBootstrap;
import com.shao.loadBalance.AbstractLoadBalancer;
import com.shao.loadBalance.Selector;
import io.netty.channel.Channel;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.TreeMap;

/**
 * @author PaoFu
 * @version 1.0
 * @data 2025/5/6 14:48
 */
@Slf4j
public class ShortestResponseTimeLoadBalancer extends AbstractLoadBalancer {

    @Override
    protected Selector getSelector(List<InetSocketAddress> addresses) {
        return new ShortestResponseTimeSelector();
    }

    @Data
    @Accessors(chain = true)
    private static class ShortestResponseTimeSelector implements Selector {

        @Override
        public InetSocketAddress getNext() {
            TreeMap<Long, Channel> shortestResponseTimeChannel = SrpcBootstrap.SHORTEST_RESPONSE_TIME_CHANNEL;
            if (shortestResponseTimeChannel.isEmpty()) {
                shortestResponseTimeChannel = tryAgainObtain();
            }
            SrpcBootstrap.SHORTEST_RESPONSE_TIME_CHANNEL.forEach((key, value) -> log.info("时间:【{}】，服务器：【{}】", key, value));
            log.info("使用了时间为【{}】、地址为【{}】的服务器", shortestResponseTimeChannel.firstKey(), shortestResponseTimeChannel.firstEntry());
            return (InetSocketAddress) shortestResponseTimeChannel.firstEntry().getValue().remoteAddress();
        }

        /**
         * 获取管道失败时重试机制
         * @return 返回channel
         */
        private TreeMap<Long, Channel> tryAgainObtain() {
            TreeMap<Long, Channel> treeMap;
            for (int i = 0; i < 10; i++) {
                try {
                    log.warn("最短响应时长第【{}】次重试获取管道", (i + 1));
                    Thread.sleep(10 * (i + 1));
                    treeMap = SrpcBootstrap.SHORTEST_RESPONSE_TIME_CHANNEL;
                    if (!treeMap.isEmpty()) {
                        return treeMap;
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            log.error("最短响应时长找不到缓存的管道");
            throw new RuntimeException("最短响应时长找不到缓存的管道");
        }
    }
}
